{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Simple Meander"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Creates 3 transmon pockets, connected in different ways by the mean of transmission lines.\n",
    "\n",
    "These transmission line QComponents create basic meanders to accommodate the user-defined line length."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Preparations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The next cell enables [module automatic reload](https://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html?highlight=autoreload). Your notebook will be able to pick up code updates made to the qiskit-metal (or other) module code."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%reload_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Import key libraries and open the Metal GUI. Also we configure the notebook to enable overwriting of existing components"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "from qiskit_metal import designs\n",
    "from qiskit_metal import MetalGUI, Dict\n",
    "\n",
    "design = designs.DesignPlanar()\n",
    "gui = MetalGUI(design)\n",
    "\n",
    "# if you disable the next line, then you will need to delete a component [<component>.delete()] before recreating it\n",
    "design.overwrite_enabled = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.core import QRouteLead"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create 3 Transmon Qbits with 4 pins. This uses the same definition (options) for all 3 Qbits, but it places them in 3 different (x,y) origin points."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket\n",
    "\n",
    "optionsQ = dict(\n",
    "    pad_width = '425 um',\n",
    "    pocket_height = '650um',\n",
    "    connection_pads = dict(  # Qbits defined to have 4 pins\n",
    "        a = dict(loc_W=+1,loc_H=+1), \n",
    "        b = dict(loc_W=-1,loc_H=+1, pad_height='30um'),\n",
    "        c = dict(loc_W=+1,loc_H=-1, pad_width='200um'),\n",
    "        d = dict(loc_W=-1,loc_H=-1, pad_height='50um')\n",
    "    )\n",
    ")\n",
    "\n",
    "q1 = TransmonPocket(design, 'Q1', options = dict(pos_x='-1.5mm', pos_y='+0.0mm', **optionsQ))\n",
    "q2 = TransmonPocket(design, 'Q2', options = dict(pos_x='+0.35mm', pos_y='+1.0mm', orientation = '90',**optionsQ))\n",
    "q3 = TransmonPocket(design, 'Q3', options = dict(pos_x='2.0mm', pos_y='+0.0mm', **optionsQ))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()\n",
    "gui.highlight_components(['Q1', 'Q2', 'Q3'])  # This is to show the pins, so we can choose what to connect"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using CPW meanders to connect the 3 Qbits"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Import the RouteMeander and inspect what options are available for you to initialize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.tlines.meandered import RouteMeander\n",
    "RouteMeander.get_template_options(design)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's define a dictionary with the options we want to keep global. We will then concatenate this dictionary to the ones we will use to describe the individual Qbits"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ops=dict(fillet='90um')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's define the first CPW QComponent."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "options = Dict(\n",
    "    total_length= '8mm',\n",
    "    hfss_wire_bonds = True,\n",
    "    pin_inputs=Dict(\n",
    "        start_pin=Dict(\n",
    "            component= 'Q1',\n",
    "            pin= 'a'),\n",
    "        end_pin=Dict(\n",
    "            component= 'Q2',\n",
    "            pin= 'b')),\n",
    "    lead=Dict(\n",
    "        start_straight='0mm',\n",
    "        end_straight='0.5mm'),\n",
    "    meander=Dict(\n",
    "       asymmetry='-1mm'),\n",
    "    **ops\n",
    ")\n",
    "\n",
    "# Below I am creating a CPW without assigning its name.\n",
    "#  Therefore running this cell twice will create two CPW's instead of overwriting the previous one\n",
    "#  To prevent that we add the cpw.delete() statement.\n",
    "#  The try-except wrapping is needed to suppress errors during the first run of this cell\n",
    "try:\n",
    "    cpw.delete()\n",
    "except NameError: pass\n",
    "\n",
    "cpw = RouteMeander(design, options=options)\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You might have received an expected python \"warning - check_lengths\" message.\n",
    "This indicates that one of the CPW edges is too short to accommodate the fillet corner rounding previous defined at 90um.\n",
    "Also, the CPW \"start lead\" does not offer enough clearance from the Qbit, causing a short between two pins.\n",
    "\n",
    "Please take a minute to observe this behavior in the GUI"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can inspect the points forming the CPW route to find the culprit edge (the warning message should have indicated the index of the offending edge)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cpw.get_points()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Turns out that both issues can be resolved by just adding enough clearance at the start of the CPW."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cpw.options['lead']['start_straight']='100um'\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice how the routing algorithm tries to prevent creation of edges too short to apply the fillet corner rounding. If your design requires it, you can disable this algorithm behavior for individual CPWs. For example try the cell below, and expect warning similar to the ones encountered earlier to show up"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cpw.options['prevent_short_edges']='false'\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can eliminate the warning by either re-enabling the algorithm, or by changing the fillet for this specific CPW. Let's try the second approach for demonstration purposes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cpw.options['fillet']='65um'\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's create other 3 CPWs for practice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "options = Dict(\n",
    "    total_length= '6mm',\n",
    "    pin_inputs=Dict(\n",
    "        start_pin=Dict(\n",
    "            component= 'Q2',\n",
    "            pin= 'd'),\n",
    "        end_pin=Dict(\n",
    "            component= 'Q3',\n",
    "            pin= 'b')),\n",
    "    lead=Dict(\n",
    "        start_straight='0.1mm',\n",
    "        end_straight='0.2mm'),\n",
    "    meander=Dict(\n",
    "       asymmetry='-0.9mm'),\n",
    "    **ops\n",
    ")\n",
    "\n",
    "try:\n",
    "    cpw2.delete()\n",
    "except NameError: pass\n",
    "\n",
    "cpw2 = RouteMeander(design,options=options)\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "options = Dict(\n",
    "    total_length= '8mm',\n",
    "    pin_inputs=Dict(\n",
    "        start_pin=Dict(\n",
    "            component= 'Q3',\n",
    "            pin= 'a'),\n",
    "        end_pin=Dict(\n",
    "            component= 'Q2',\n",
    "            pin= 'c')),\n",
    "    lead=Dict(\n",
    "        start_straight='0.5mm',\n",
    "        end_straight='0.1mm'),\n",
    "    meander=Dict(\n",
    "       asymmetry='-1mm'),\n",
    "    **ops\n",
    ")\n",
    "\n",
    "try:\n",
    "    cpw3.delete()\n",
    "except NameError: pass\n",
    "\n",
    "cpw3 = RouteMeander(design,options=options)\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "options = Dict(\n",
    "    total_length= '8mm',\n",
    "    pin_inputs=Dict(\n",
    "        start_pin=Dict(\n",
    "            component= 'Q1',\n",
    "            pin= 'b'),\n",
    "        end_pin=Dict(\n",
    "            component= 'Q2',\n",
    "            pin= 'a')),\n",
    "    lead=Dict(\n",
    "        start_straight='0.5mm',\n",
    "        end_straight='0.1mm'),\n",
    "    meander=Dict(\n",
    "       asymmetry='1mm'),\n",
    "    **ops\n",
    ")\n",
    "\n",
    "try:\n",
    "    cpw4.delete()\n",
    "except NameError: pass\n",
    "\n",
    "cpw4 = RouteMeander(design,options=options)\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's try a more complex utilization of the leads. So far we have demonstrated `lead->start_straight` and `lead->end_straight`. We can \"append\" to the straight lead any number of custom jogs, which might be useful to get out of complex layout arrangements or to fine tune the meander in case of collisions with other components.\n",
    "\n",
    "To define a jogged lead, you need an ordered sequence of turn-length pairs, which we define here as an ordered dictionary. We then apply the sequence of jogs to both the start and end leads (or you could apply it to only one them, or you can define the two leads separately with two ordered dictionaries)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import OrderedDict\n",
    "jogs = OrderedDict()\n",
    "jogs[0] = [\"L\", '800um']\n",
    "jogs[1] = [\"L\", '500um']\n",
    "jogs[2] = [\"R\", '200um']\n",
    "jogs[3] = [\"R\", '500um']\n",
    "\n",
    "options = Dict(\n",
    "    total_length= '14mm',\n",
    "    pin_inputs=Dict(\n",
    "        start_pin=Dict(\n",
    "            component= 'Q1',\n",
    "            pin= 'd'),\n",
    "        end_pin=Dict(\n",
    "            component= 'Q3',\n",
    "            pin= 'd')),\n",
    "    lead=Dict(\n",
    "        start_straight='0.1mm',\n",
    "        end_straight='0.1mm',\n",
    "        start_jogged_extension=jogs,\n",
    "        end_jogged_extension=jogs),\n",
    "    meander=Dict(\n",
    "       asymmetry='-1.2mm'),\n",
    "    **ops\n",
    ")\n",
    "\n",
    "try:\n",
    "    cpw5.delete()\n",
    "except NameError: pass\n",
    "\n",
    "cpw5 = RouteMeander(design,options=options)\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here a few additional examples routing flexibility on a brand-new set of Qbits"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "q4 = TransmonPocket(design, 'Q4', options = dict(pos_x='-7.5mm', pos_y='-0.5mm', **optionsQ))\n",
    "q5 = TransmonPocket(design, 'Q5', options = dict(pos_x='-5.65mm', pos_y='+0.5mm', orientation = '90',**optionsQ))\n",
    "q6 = TransmonPocket(design, 'Q6', options = dict(pos_x='-4.0mm', pos_y='-0.6mm', **optionsQ))\n",
    "gui.rebuild()\n",
    "\n",
    "options = Dict(\n",
    "    total_length= '3.4mm',\n",
    "    pin_inputs=Dict(\n",
    "        start_pin=Dict(\n",
    "            component= 'Q4',\n",
    "            pin= 'a'),\n",
    "        end_pin=Dict(\n",
    "            component= 'Q5',\n",
    "            pin= 'b')),\n",
    "    lead=Dict(\n",
    "        start_straight='0.5mm',\n",
    "        end_straight='0.1mm'),\n",
    "    meander=Dict(\n",
    "       asymmetry='1mm'),\n",
    "    **ops\n",
    ")\n",
    "try:\n",
    "    cpw6.delete()\n",
    "except NameError: pass\n",
    "cpw6 = RouteMeander(design, options=options)\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "options = Dict(\n",
    "    total_length= '12mm',\n",
    "    pin_inputs=Dict(\n",
    "        start_pin=Dict(\n",
    "            component= 'Q4',\n",
    "            pin= 'd'),\n",
    "        end_pin=Dict(\n",
    "            component= 'Q6',\n",
    "            pin= 'c')),\n",
    "    lead=Dict(\n",
    "        start_straight='0.1mm',\n",
    "        end_straight='0.1mm'),\n",
    "    meander=Dict(\n",
    "       asymmetry='-1.2mm'),\n",
    "    **ops\n",
    ")\n",
    "try:\n",
    "    cpw7.delete()\n",
    "except NameError: pass\n",
    "cpw7 = RouteMeander(design, options=options)\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "options = Dict(\n",
    "    total_length= '13mm',\n",
    "    pin_inputs=Dict(\n",
    "        start_pin=Dict(\n",
    "            component= 'Q6',\n",
    "            pin= 'a'),\n",
    "        end_pin=Dict(\n",
    "            component= 'Q4',\n",
    "            pin= 'b')),\n",
    "    lead=Dict(\n",
    "        start_straight='0.1mm',\n",
    "        end_straight='0.1mm'),\n",
    "    meander=Dict(\n",
    "       asymmetry='-1.7mm'),\n",
    "    **ops\n",
    ")\n",
    "try:\n",
    "    cpw8.delete()\n",
    "except NameError: pass\n",
    "cpw8 = RouteMeander(design, options=options)\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#If you would like to close the GUI. Remove the comment.\n",
    "#gui.main_window.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
